// Copyright 2011-2012, Vanya Davidenko.
// Используемая кодировка: UTF-8.

#ifndef LIBV_BOOST_XML_XML_ATTRIBUTE_H_
#define LIBV_BOOST_XML_XML_ATTRIBUTE_H_

#include <string>
#include <libv/boost/shared_ptr.h>
#include <libv/boost/xml/xml_node.h>
#include <libv/check.h>
#include "rapidxml.h"



namespace libv {

class XmlNode;

// Обертка для чтения rapidxml::xml_attribute, имеющая специальное нулевое
// состояние, используемое для обозначения отсутствия атрибута.
class XmlAttribute {
  friend class XmlNode;  // для XmlAttributeIterator
  public:
    // Создание нулевого объекта.
    XmlAttribute()
        : pimpl_(NULL) {}

    // Атрибут находится в нулевом состоянии.
    bool IsNull() const {
        return pimpl_ == NULL;
    }


    bool operator==(const XmlAttribute& rhv) const {
        if ( IsNull() || rhv.IsNull() ) {
            return IsNull() == rhv.IsNull();
        }
        return pimpl_ == rhv.pimpl_;
    }

    bool operator!=(const XmlAttribute& rhv) const {
        return !(*this == rhv);
    }


    // Имя атрибута.
    // @pre !IsNull()
    ::std::string Name() const {
        LIBV_PRECOND(!IsNull());
        if ( pimpl_->name_size() == 0 ) {
            return ::std::string();
        }
        return ::std::string(pimpl_->name(), pimpl_->name_size());
    }

    // Значение атрибута.
    // @pre !IsNull()
    ::std::string Value() const {
        LIBV_PRECOND(!IsNull());
        if ( pimpl_->value_size() == 0 ) {
            return ::std::string();
        }
        return ::std::string(pimpl_->value(), pimpl_->value_size());
    }

    // Узел, содержащий атрибут.
    const XmlNode& Node() const {
        return *node_;
    }

  private:
    explicit XmlAttribute(const rapidxml::xml_attribute<>* pimpl,
                          const XmlNode* node)
      : pimpl_(pimpl),
        node_(node) {}

    const rapidxml::xml_attribute<>* pimpl_;

    // Указатель здесь ни к чему, но иначе циклическая зависимость:
    // XmlNode <-> XmlAttribute.
    libv::shared_ptr<const XmlNode> node_;
};

}  // libv

#endif  // LIBV_BOOST_XML_XML_ATTRIBUTE_H_
